package com.app.common.adapter

import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView

abstract class GroupAdapter<D : Any, VH : RecyclerView.ViewHolder> : RecyclerView.Adapter<VH>() {

    companion object {
        const val GROUP = 1
    }

    protected val items = mutableListOf<D>()

    fun isGroup(position: Int): Boolean = getItemViewType(position) == GROUP
    abstract fun isNeedAddGroupItem(item: D, preItem: D): Boolean
    abstract fun getGroupTitle(item: D): String
    abstract fun isGroupItem(item: D?): Boolean
    abstract fun toGroupItem(item: D): D
    abstract fun onCreateSelectionViewHolder(parent: ViewGroup, viewType: Int): VH
    abstract fun onCreateGroupViewHolder(parent: ViewGroup, viewType: Int): VH
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
        return if (viewType == GROUP) {
            onCreateGroupViewHolder(parent, viewType)
        } else {
            onCreateSelectionViewHolder(parent, viewType)
        }
    }

    override fun getItemViewType(position: Int): Int {
        return if (items[position].isGroup()) GROUP else 0
    }

    override fun getItemCount(): Int = items.size
    fun getItem(position: Int): D? {
        val item = items[position]
        return if (item.isGroup()) {
            null
        } else {
            item as D
        }
    }


    fun setItems(items: List<D>) {
        if (items.isEmpty()) {
            return
        }
        this.items.clear()
        addItemsByGroup(items)
        notifyItemRangeInserted(0, this.items.size)
//        notifyDataSetChanged()
        println("=========setItems:${this.items.size}")
    }


    fun addItems(items: List<D>) {
        val sp = this.items.size
        val groupSize = addItemsByGroup(items)
        notifyItemRangeInserted(sp, items.size + groupSize)
    }

    fun removeItem(position: Int) {
        println("=========removeItem:$position , ${items.size}")
        if (position >= items.size) {
            return
        }

        if (!items[position].isGroup()) {
            items.removeAt(position)
            if (items.isNotEmpty() && position == items.size) {
                //notifyItemRemoved(position)
                if (items.getOrNull(position - 1).isGroup()) {
                    items.removeAt(position - 1)
                    //notifyItemRemoved(position-1)
                }
            }
            if (position < items.size) {
                //notifyItemRemoved(position)
            } else {
                return
            }
            val pre = position - 1
            if (position < items.size && items[position].isGroup() && items[pre].isGroup()) {
                items.removeAt(pre)
                //notifyItemRemoved(pre)
            } else if (position == items.size) {
                items.clear()
                //notifyItemRangeRemoved(0, itemCount)
            }
        }
    }

    protected fun D?.isGroup(): Boolean {
        return isGroupItem(this)
    }

    private fun addItemsByGroup(items: List<D>): Int {
        if (items.isEmpty()) {
            return 0
        }
        var preItem: D
        val first = items.first()
        var groupCount = 0
        var lastGroupTitle = ""
        if (this.items.isEmpty()) {
            preItem = first
            groupCount = 1
            lastGroupTitle = getGroupTitle(preItem)
            this.items += toGroupItem(preItem)
        } else {
            preItem = this.items.last() as D
            if (isNeedAddGroupItem(first, preItem)) {
                groupCount = 1
                preItem = first
                lastGroupTitle = getGroupTitle(first)
                this.items += toGroupItem(first)
            }
        }
        this.items += first

        if (items.size >= 2) {
            var item: D
            for (i in 1 until items.size) {
                item = items[i]
                if (isNeedAddGroupItem(item, preItem)) {
                    groupCount++
                    this.items += toGroupItem(item)
                }
                this.items += item
                preItem = item
            }
        }
        return groupCount
    }
}